---
import { type CollectionEntry, getCollection } from "astro:content";
import { render } from "astro:content";
import BaseHead from "@components/BaseHead.astro";
import Translations from "@components/Translations.astro";
import { toIso8601Full } from "@utils/datetime";
import ReadingTime from "@components/ReadingTime.astro";
import Keywords from "@components/Keywords.astro";
import Citations from "@components/Citations.astro";
import Signature from "@components/signature/Signature.astro";
import CopyrightNotice from "@components/CopyrightNotice.astro";
import { verifier as verifierPrototype } from "@lib/pgp/verify";
import { getSigners } from "@lib/collection/helpers";
import { get } from "@utils/anonymous";
import Authors from "@components/signature/Authors.astro";
import { getEntry } from "astro:content";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.id },
props: post,
}));
}
type Props = CollectionEntry<"blog">;
const post = Astro.props;
let original: CollectionEntry<"blog">;
if (post.data.kind === "translation") {
original = await getEntry(
post.data.translationOf as CollectionEntry<"blog">,
);
if (!original) {
throw new Error(`Original post not found for ${post.id}`);
}
const originalAuthor = (original.data.signers ?? []).filter(
(s) => s.role === "author",
).map((s) => s.entity.id)?.[0];
const originalCoAuthors = new Set(
(original.data.signers ?? []).filter(
(s) => s.role === "co-author",
).map((s) => s.entity.id),
);
const translationAuthor = (post.data.signers ?? []).filter(
(s) => s.role === "author",
).map((s) => s.entity.id)?.[0];
const translationCoAuthors = new Set(
(post.data.signers ?? []).filter(
(s) => s.role === "co-author",
).map((s) => s.entity.id),
);
if (
(translationAuthor !== undefined &&
translationAuthor !== originalAuthor) ||
!translationCoAuthors.isSubsetOf(originalCoAuthors)
) {
throw new Error(
`Post ${post.id} has mismatched (co-)authors from original post ${original.id}`,
);
}
const translators = (post.data.signers ?? []).filter(
(s) => s.role === "translator",
).map((s) => s.entity.id);
for (const translator of translators) {
if (
originalAuthor === translator || originalCoAuthors.has(translator)
) {
throw new Error(
`Translator ${translator} in ${post.id} is already a (co-)author in original post`,
);
}
}
} else {
original = post;
if (post.data.signers?.some((x) => x.role === "translator")) {
throw new Error(
`Post ${post.id} is not a translation but has translators defined`,
);
}
}
// Add own post as a translation
const translationsSet = new Set(
(await getCollection(
"blog",
(x) =>
(x.data.kind === "translation") && x.data.translationOf.id ===
(post.data.kind === "translation"
? post.data.translationOf.id
: post.id),
) ?? []).map(({ id }) => id),
);
translationsSet.add(post.id);
const translations = [...translationsSet.values()].map((id) => ({
collection: post.collection,
id,
}));
const signers = await getSigners(post);
const verifier = await verifierPrototype.then((x) => x.clone());
// Add signers public keys to keyring
for (const { data } of signers.map(get("entity"))) {
if (data.publickey.armor !== undefined) {
verifier.addKeyFromArmor(data.publickey.armor);
}
}
const verification = post.filePath !== undefined
? await verifier.verify([
new URL(`file://${Deno.cwd()}/${post.filePath}`),
])
: undefined;
const { Content } = await render(post);
const { lang } = post.data;
const commit = await verification?.commit;
---
{post.data.title}
{
"subtitle" in post.data && (
{post.data.subtitle}
)
}
{
"description" in post.data && post.data.description &&
(
Resumo
{
post.data.description.split(new RegExp("\\s{2,}"))
.map((
x,
) => (
{x}
))
}
)
}
{verification && }
{
"keywords" in original.data && (
)
}
{
"relatedPosts" in original.data && (
)
}